package javaer.starter.core;

import javaer.starter.base.domain.dto.DependencyDTO;
import javaer.starter.base.domain.dto.NewProjectDefinition;
import javaer.starter.core.metadata.PomXml;
import javaer.starter.core.parser.ModulePomXmlParser;
import javaer.starter.core.parser.RootPomXmlParser;
import javaer.starter.util.ArtifactIdUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 项目定义解析
 *
 * @author yangzhen
 * @date 2023/6/15 16:56
 * @since 1.0.0
 */
@Component
public class ProjectDefinitionParser {

    @Resource
    private RootPomXmlParser rootPomXmlParser;
    @Resource
    private ModulePomXmlParser modulePomXmlParser;

    public BuildContext parse(NewProjectDefinition projectDefinition) throws Exception {

        BuildContext buildContext = new BuildContext();
        buildContext.setProjectName(projectDefinition.getArtifactId());
        buildContext.setTypeId(projectDefinition.getTypeId());
        buildContext.setTypeName(projectDefinition.getTypeId().toLowerCase());

        // root解析
        List<PomXml> parent = rootPomXmlParser.parse(projectDefinition);
        buildContext.setParentModule(parent.get(0));
        // module解析
        List<PomXml> childModules = modulePomXmlParser.parse(projectDefinition);
        if (childModules != null && !childModules.isEmpty()) {
            Map<Boolean, List<PomXml>> moduleGroup = childModules.stream().collect(Collectors.groupingBy(pom -> pom.getImStarterPom()));
            buildContext.setStarterModule(moduleGroup.get(Boolean.TRUE).get(0));
            buildContext.setChildModules(moduleGroup.get(Boolean.FALSE));
        }
        if (buildContext.getStarterModule() == null) {
            throw new RuntimeException("脚手架没有启动模块");
        }
        getDependencyManagement(buildContext);
        trySingleProject(buildContext);
        return buildContext;
    }

    private void getDependencyManagement(BuildContext buildContext) {
        PomXml parentModule = buildContext.getParentModule();
        Map<String, String> properties = parentModule.getProperties();
        Set<DependencyDTO> dependencyManagement = Optional.ofNullable(parentModule.getDependencyManagement()).orElse(new HashSet<>());
        parentModule.setDependencyManagement(dependencyManagement);

        dealDependencyManagement(properties, dependencyManagement, Collections.singletonList(buildContext.getStarterModule()));
        dealDependencyManagement(properties, dependencyManagement, buildContext.getChildModules());
    }

    /**
     * 解析子module的依赖，填充到root pom中，包括
     * properties
     * dependencyManagement
     *
     * @param properties
     * @param dependencyManagement
     * @param pomXmlList
     */
    private void dealDependencyManagement(Map<String, String> properties, Set<DependencyDTO> dependencyManagement, List<PomXml> pomXmlList) {
        if (CollectionUtils.isNotEmpty(pomXmlList)) {
            pomXmlList.forEach(pomXml -> {
                Set<DependencyDTO> dependencies = pomXml.getDependencies();
                if (CollectionUtils.isNotEmpty(dependencies)) {
                    dependencies.forEach(dep -> {
                        String artifactId = dep.getArtifactId();
                        String versionLabel = ArtifactIdUtil.toPropertyVersionLabel(artifactId);
                        String hasVersion = properties.get(versionLabel);
                        if (StringUtils.isBlank(hasVersion)) {
                            properties.put(versionLabel, dep.getVersion());
                        }
                        dep.setVersion(null);
                        DependencyDTO dependencyDTO = new DependencyDTO();
                        BeanUtils.copyProperties(dep, dependencyDTO);
                        dependencyDTO.setVersion(ArtifactIdUtil.toVersionRef(versionLabel));
                        dependencyManagement.add(dependencyDTO);
                    });
                }
            });
        }
    }

    /**
     * 业务模块为空 && 模块为空 单一应用
     * 否则 不做处理
     *
     * @param buildContext
     */
    private void trySingleProject(BuildContext buildContext) {
        PomXml parentModule = buildContext.getParentModule();
        PomXml starterModule = buildContext.getStarterModule();
        List<PomXml> childModules = buildContext.getChildModules();
        if (CollectionUtils.isEmpty(childModules)) {
            buildContext.setSingle(true);
            parentModule.setImStarterPom(true);
            parentModule.getModules().clear();
            Set<DependencyDTO> dependencies = starterModule.getDependencies();
            parentModule.setMainClass(starterModule.getMainClass());
            if (CollectionUtils.isNotEmpty(dependencies)) {
                Set<DependencyDTO> parentDependencies = parentModule.getDependencies();
                if (CollectionUtils.isEmpty(parentDependencies)) {
                    parentDependencies = new HashSet<>();
                    parentModule.setDependencies(parentDependencies);
                }
                parentDependencies.addAll(dependencies);
            }
        }
    }
}
